//
//  VCImageProcessing.m
//  VCardPro
//
//  Created by Nguyen Thong Thai on 9/18/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "VCImageProcessing.h"

@implementation VCImageProcessing

@synthesize originalImg;

#pragma mark - Class Methods


+ (UIImage *)normalizeImage:(UIImage *)anImage
{
    int kMaxResolution = 320; // Or whatever
    
    CGImageRef imgRef = anImage.CGImage;
    
    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);
    
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = bounds.size.width / ratio;
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }
    
    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = anImage.imageOrientation;
    switch(orient) {
            
        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;
            
        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;
            
        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;
            
        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
            
        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
            
        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
            
        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
            
        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
            
    }
    
    UIGraphicsBeginImageContext(bounds.size);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }
    
    CGContextConcatCTM(context, transform);
    
    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return imageCopy;
}

+ (UIImage *)convertRGBAToGrayScaleImage:(UIImage *)anImage
{
/*
    anImage = [self normalizeImage:anImage]; //THIS IS WHERE REPAIR THE ROTATION PROBLEM
    
    // Create image rectangle with current image width/height
    CGRect imageRect = CGRectMake(0, 0, anImage.size.width, anImage.size.height);
    
    // Grayscale color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    
    // Create bitmap content with current image size and grayscale colorspace
    CGContextRef context = CGBitmapContextCreate(nil,
                                                 anImage.size.width,
                                                 anImage.size.height,
                                                 8,
                                                 anImage.size.width,
                                                 colorSpace,
                                                 kCGImageAlphaNone);
    
    // Draw image into current context, with specified rectangle
    // using previously defined context (with grayscale colorspace)
    CGContextDrawImage(context, imageRect, [anImage CGImage]);
    
    // Create bitmap image info from pixel data in current context
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    
    // Create a new UIImage object  
    UIImage *newImage = [UIImage imageWithCGImage:imageRef];
    
    // Release colorspace, context and bitmap information
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    //CFRelease(imageRef);
    
    // Return the new grayscale image
    return newImage; 
*/
    anImage = [self normalizeImage:anImage]; //THIS IS WHERE REPAIR THE ROTATION PROBLEM
    
    // Create image rectangle with current image width/height
    CGRect imageRect = CGRectMake(0, 0, anImage.size.width, anImage.size.height);
    
    // Grayscale color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    
    // Create bitmap content with current image size and grayscale colorspace
    CGContextRef context = CGBitmapContextCreate(nil,
                                                 anImage.size.width,
                                                 anImage.size.height,
                                                 8,
                                                 anImage.size.width,
                                                 colorSpace,
                                                 kCGImageAlphaNone);
    
    // Draw image into current context, with specified rectangle
    // using previously defined context (with grayscale colorspace)
    CGContextDrawImage(context, imageRect, [anImage CGImage]);
    
    // Create bitmap image info from pixel data in current context
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    
    // Create a new UIImage object  
    UIImage *newImage = [UIImage imageWithCGImage:imageRef];
    
    // Release colorspace, context and bitmap information
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    //CFRelease(imageRef);
    
    // Return the new grayscale image
    return newImage; 
}

+ (UIImage *)binarizeImageUsingOtsuMethod:(UIImage *)image
{
    int width = image.size.width;
    int height = image.size.height;
    int size = width * height * 4;
    
    int histogramData[256];
    unsigned char *imageData = [VCImageProcessing convertUIImageToBitmapRGBA:image];
    int ptr;
    
    // Set all values of histogram to zero
    ptr = 0;
    while (ptr < 256) histogramData[ptr++] = 0;
    
    // Calculate histogram and find the level with the max value
    ptr = 0;
    int maxLevelValue = 0;
    while (ptr < size) {
        int h = 0xFF & imageData[ptr];
        histogramData[h]++;
        if (histogramData[h] > maxLevelValue) maxLevelValue = histogramData[h];
        ptr++;
    }
    
    // Total number of pixels
    int total = size;
    
    float sum = 0;
    for (int i = 0; i < 256; i++) {
        sum += i * histogramData[i];
    }
    
    float sumB = 0;
    int wB = 0;
    int wF = 0;
    
    float varMax = 0;
    int threshold = 0;
    
    for (int i = 0 ; i < 256; i++) {
        wB += histogramData[i];					// Weight Background
        if (wB == 0) continue;
        
        wF = total - wB;						// Weight Foreground
        if (wF == 0) break;
        
        sumB += (float) (i * histogramData[i]);
        
        float mB = sumB / wB;				// Mean Background
        float mF = (sum - sumB) / wF;		// Mean Foreground
        
        // Calculate Between Class Variance
        float varBetween = (float)wB * (float)wF * (mB - mF) * (mB - mF);	
        
        // Check if new maximum found
        if (varBetween > varMax) {
            varMax = varBetween;
            threshold = i;
        }
    }
    
    unsigned char* resultData = (unsigned char*)malloc(size);
    // Apply threshold to create binary image
    NSLog(@"Threshold: %d", threshold);
    if (resultData != nil) {
        ptr = 0;
        while (ptr < size) {
            resultData[ptr] = ((0xFF & imageData[ptr]) >= threshold) ? 255 : 0;
            ptr++;
        }
    }

    UIImage *resultUIImage = [VCImageProcessing convertBitmapRGBAToUIImage:resultData withWidth:width withHeight:height];
    return resultUIImage;
    /*CGContextRef ctx = CGBitmapContextCreate(resultData,
                                             CGImageGetWidth(grayscaleImage.CGImage),
                                             CGImageGetHeight(grayscaleImage.CGImage),
                                             8,
                                             CGImageGetBytesPerRow(grayscaleImage.CGImage),
                                             CGImageGetColorSpace(grayscaleImage.CGImage),
                                             kCGImageAlphaNone);
    
    
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage* rawImage = [UIImage imageWithCGImage:imageRef];
    CGContextRelease(ctx);
    */
    //return rawImage;    
}

+ (UIImage *)convertBitmapRGBAToUIImage:(unsigned char *) buffer
                              withWidth:(int) width
                             withHeight:(int) height 
{
    size_t bufferLength = width * height * 4;
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL);
    size_t bitsPerComponent = 8;
    size_t bitsPerPixel = 32;
    size_t bytesPerRow = 4 * width;
    
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    if(colorSpaceRef == nil) {
        CGDataProviderRelease(provider);
        return nil;
    }
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    
    CGImageRef iref = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, nil, YES, renderingIntent);
    
    uint32_t* pixels = (uint32_t*)malloc(bufferLength);
    
    if (pixels == nil) {
        CGDataProviderRelease(provider);
        CGColorSpaceRelease(colorSpaceRef);
        CGImageRelease(iref);	
        return nil;
    }
    
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, bitsPerComponent, bytesPerRow, colorSpaceRef, bitmapInfo);
    
    if(context == nil) {
        free(pixels);
    }
    
    UIImage *image = nil;
    if (context) {
        CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref);
        CGImageRef imageRef = CGBitmapContextCreateImage(context);
        if([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) {
            float scale = [[UIScreen mainScreen] scale];
            image = [UIImage imageWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
        } else {
            image = [UIImage imageWithCGImage:imageRef];
        }
        
        CGImageRelease(imageRef);	
        CGContextRelease(context);	
    }
    
    CGColorSpaceRelease(colorSpaceRef);
    CGImageRelease(iref);
    CGDataProviderRelease(provider);
    
    if (pixels) {
        free(pixels);
    }	
    return image;
}

+ (unsigned char *) convertUIImageToBitmapRGBA:(UIImage *)image {
    CGImageRef imageRef = image.CGImage;
    // Create a bitmap context to draw the uiimage into
    CGContextRef context = [self newBitmapRGBAContextFromImage:imageRef];
    if (!context) {
        return nil;
    }
    
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    
    CGRect rect = CGRectMake(0, 0, width, height);
    
    // Draw image into the context to get the raw image data
    CGContextDrawImage(context, rect, imageRef);
    
    // Get a pointer to the data
    unsigned char *bitmapData = (unsigned char *)CGBitmapContextGetData(context);
    
    // Copy the data and release the memory (return memory allocated with new)
    size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context);
    size_t bufferLength = bytesPerRow * height;
    
    unsigned char *newBitmap = NULL;
    
    if (bitmapData) {
        newBitmap = (unsigned char *)malloc(sizeof(unsigned char) * bytesPerRow * height);
        
        if (newBitmap) {	// Copy the data
            for(int i = 0; i < bufferLength; ++i) {
                newBitmap[i] = bitmapData[i];
            }
        }
        
        free(bitmapData);
        
    }
    CGContextRelease(context);
    
    return newBitmap;	
}

+ (CGContextRef)newBitmapRGBAContextFromImage:(CGImageRef)image 
{
    CGContextRef context = NULL;
    CGColorSpaceRef colorSpace;
    uint32_t *bitmapData;
    
    size_t bitsPerPixel = 32;
    size_t bitsPerComponent = 8;
    size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
    
    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);
    
    size_t bytesPerRow = width * bytesPerPixel;
    size_t bufferLength = bytesPerRow * height;
    
    colorSpace = CGColorSpaceCreateDeviceRGB();
    
    if (!colorSpace) {
        return nil;
    }
    
    // Allocate memory for image data
    bitmapData = (uint32_t *)malloc(bufferLength);
    
    if (!bitmapData) {
        CGColorSpaceRelease(colorSpace);
        return nil;
    }
    
    //Create bitmap context
    context = CGBitmapContextCreate(bitmapData,
                                    width,
                                    height,
                                    bitsPerComponent,
                                    bytesPerRow,
                                    colorSpace,
                                    kCGImageAlphaPremultipliedLast);	    
    if (!context) {
        free(bitmapData);
    }
    CGColorSpaceRelease(colorSpace);
    
    return context;	
}

+ (UIImage *)autoCroppedImage:(UIImage *)image
{
     int imgWidth = image.size.width;
     int imgHeight = image.size.height;
     //int pixel[imgWidth][imgHeight];    
     
     for (int y = 0; y < imgWidth; y++) {
         for (int x = 0; x < imgHeight; x++) {
    //         int rbgValue = [VCImageProcessing rbgValueAtPixel:CGPointMake(x, y) image:image];
             
         }
     }
     
     //pixel[i][j] = 
     
     //int imgWidth = imageData.getWidth();
     //int imgHeight = imageData.getHeight();
     //int[][] pixelRGB = new int[imgWidth][imgHeight];
     //HashMap<Integer, Integer> colorCount = new HashMap<Integer, Integer>();
     //Integer count = new Integer(0);
     
/*     for(int w = 0; w < imgWidth; w++){
     for(int h = 0; h < imgHeight; h++){
     pixelRGB[w][h] = imageData.getRGB(w, h);
     
     count = colorCount.get(pixelRGB[w][h]);
     colorCount.put(pixelRGB[w][h], count == null? 1 : count + 1);
     
     
     
     // Determine background (dominant) color
     int background = 0;
     int max = 0;
     int value = 0;
     for(Map.Entry<Integer, Integer> entry: colorCount.entrySet()){
     value = entry.getValue();
     if(value > max){
     max = value;
     background = entry.getKey();
     
    
     // Search for 4 corners of the image that are not dominant color
     NSInteger topX = 0;
     NSInteger topY = 0;
     NSInteger leftX = 0;
     NSInteger leftY = 0;
     NSInteger rightX = imgWidth;
     NSInteger rightY = imgHeight;
     NSInteger bottomX = imgWidth;
     NSInteger bottomY = imgHeight;
     
     NSInteger x = 0;
     NSInteger y = 0;
     UIColor *pixelColor;
     NSInteger diffRGBA = 0;
     double threshold = 0.10; // Threshold for the difference is 5 percent
     
     // - Go down from the top to search for the first pixel that is not the background
     for (int y = 0; y < imgHeight; y++) {
     for(int x = 0; x < imgWidth; x++) {
     pixelColor = [self colorAtPixel:CGPointMake(x, y) image:self.originImage];
     const CGFloat *imgComponents = CGColorGetComponents([pixelColor CGColor]);
     CGFloat red = imgComponents[0];
     CGFloat green = imgComponents[1];
     CGFloat blue = imgComponents[2];
     CGFloat alpha = imgComponents[3];
     diffRGBA = abs();
     diffRGBA = abs(pixelColor.getRed() - bgColor.getRed());
     diffRGBA += Math.abs(pixelColor.getGreen() - bgColor.getGreen());
     diffRGBA += Math.abs(pixelColor.getBlue() - bgColor.getBlue());
     diffRGBA += Math.abs(pixelColor.getAlpha() - bgColor.getAlpha());
     
     if(diffRGBA >= threshold * 4.0 * 255.0){
     topX = x;
     topY = y;
     break;
     }
     }
     if(diffRGBA >= threshold * 4.0 * 255.0){
     break;
     }
     }
     System.out.println(" ** Top = (" + topX + ", " + topY + ")");
     //Color topColor = new Color(pixelRGB[topX][topY]);
     //System.out.println(" --- Top RGB = " + pixelRGB[topX][topY]);
     //System.out.println(" --- Top Color = " + topColor.toString());
     //System.out.println(" --- Top Alpha = " + topColor.getAlpha());
     //scannedImage.setRGB(topX, topY, Color.RED.getRGB());
     
     // - Go right from the left-side to search for the first pixel that is not the background
     for(x = 0; x < imgWidth; x++){
     for(y = 0; y < imgHeight; y++){
     pixelColor = new Color(pixelRGB[x][y]);
     diffRGBA = Math.abs(pixelColor.getRed() - bgColor.getRed());
     diffRGBA += Math.abs(pixelColor.getGreen() - bgColor.getGreen());
     diffRGBA += Math.abs(pixelColor.getBlue() - bgColor.getBlue());
     diffRGBA += Math.abs(pixelColor.getAlpha() - bgColor.getAlpha());
     
     if(diffRGBA >= threshold * 4.0 * 255.0){
     leftX = x;
     leftY = y;
     break;
     }
     }
     if(diffRGBA >= threshold * 4.0 * 255.0){
     break;
     }
     }
     System.out.println(" ** Left = (" + leftX + ", " + leftY + ")");
     //Color leftColor = new Color(pixelRGB[leftX][leftY]);
     //System.out.println(" --- Left RGB = " + pixelRGB[leftX][leftY]);
     //System.out.println(" --- Left Color = " + leftColor.toString());
     //System.out.println(" --- Left Alpha = " + leftColor.getAlpha());
     //scannedImage.setRGB(leftX, leftY, Color.RED.getRGB());
     
     // - Go up from the bottom to search for the first pixel that is not the background
     for(y = imgHeight - 1; y >= 0; y--){
     for(x = imgWidth - 1; x >= 0; x--){
     pixelColor = new Color(pixelRGB[x][y]);
     diffRGBA = Math.abs(pixelColor.getRed() - bgColor.getRed());
     diffRGBA += Math.abs(pixelColor.getGreen() - bgColor.getGreen());
     diffRGBA += Math.abs(pixelColor.getBlue() - bgColor.getBlue());
     diffRGBA += Math.abs(pixelColor.getAlpha() - bgColor.getAlpha());
     
     if(diffRGBA >= threshold * 4.0 * 255.0){
     bottomX = x;
     bottomY = y;
     break;
     }
     }
     if(diffRGBA >= threshold * 4.0 * 255.0){
     break;
     }
     }
     System.out.println(" ** Bottom = (" + bottomX + ", " + bottomY + ")");
     //Color bottomColor = new Color(pixelRGB[bottomX][bottomY]);
     //System.out.println(" --- Bottom RGB = " + pixelRGB[bottomX][bottomY]);
     //System.out.println(" --- Bottom Color = " + bottomColor.toString());
     //System.out.println(" --- Bottom Alpha = " + bottomColor.getAlpha());
     //scannedImage.setRGB(bottomX, bottomY, Color.RED.getRGB());
     
     // - Go left from the right-side to search for the first pixel that is not the background
     for(x = imgWidth - 1; x >= 0; x--){
     for(y = imgHeight - 1; y >= 0; y--){
     pixelColor = new Color(pixelRGB[x][y]);
     diffRGBA = Math.abs(pixelColor.getRed() - bgColor.getRed());
     diffRGBA += Math.abs(pixelColor.getGreen() - bgColor.getGreen());
     diffRGBA += Math.abs(pixelColor.getBlue() - bgColor.getBlue());
     diffRGBA += Math.abs(pixelColor.getAlpha() - bgColor.getAlpha());
     
     if(diffRGBA >= threshold * 4.0 * 255.0){
     rightX = x;
     rightY = y;
     break;
     }
     }
     if(diffRGBA >= threshold * 4.0 * 255.0){
     break;
     }
     }
     System.out.println(" ** Right = (" + rightX + ", " + rightY + ")");
     //Color rightColor = new Color(pixelRGB[rightX][rightY]);
     //System.out.println(" --- Right RGB = " + pixelRGB[rightX][rightY]);
     //System.out.println(" --- Right Color = " + rightColor.toString());
     //System.out.println(" --- Right Alpha = " + rightColor.getAlpha());
     //scannedImage.setRGB(rightX, rightY, Color.RED.getRGB());
     
     // Crop from the original image based on the 4 corners
     int shortMargin = 2;
     int longMargin = 5;
     int subX = 0, subY = 0, subWidth = 0, subHeight = 0;
     if((leftX == topX) && (leftY == topY)){
     subX = Math.max(leftX - shortMargin, 0);
     subY = Math.max(topY - shortMargin, 0);
     }else{
     subX = Math.max(leftX - longMargin, 0);
     subY = Math.max(topY - longMargin, 0);
     }
     
     if((rightX == bottomX) && (rightY == bottomY)){
     subWidth = Math.min((rightX + shortMargin) - subX, imgWidth - subX);
     subHeight = Math.min((bottomY + shortMargin) - subY, imgHeight - subY);
     }else{
     subWidth = Math.min((rightX + longMargin) - subX, imgWidth - subX);
     subHeight = Math.min((bottomY + longMargin) - subY, imgHeight - subY);
     }
     
     System.out.println(" + Sub = (" + subX + ", " + subY + ") ");
     System.out.println(" ++ Sub Width = " + subWidth + ", Height = " + subHeight);
     imageData = imageData.getSubimage(subX, subY, subWidth, subHeight);
 */
         return nil;
}

+ (int)rbgValueAtPixel:(CGPoint)point image:(UIImage *)image     
{
    NSUInteger width = image.size.width;
    NSUInteger height = image.size.height;
    // Cancel if point is outside image coordinates
    if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, width, height), point)) {
        return 0;
    }
    
    // Create a 1x1 pixel byte array and bitmap context to draw the pixel into.
    NSInteger pointX = trunc(point.x);
    NSInteger pointY = trunc(point.y);
    CGImageRef cgImage = image.CGImage;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData, 
                                                 1,
                                                 1,
                                                 bitsPerComponent, 
                                                 bytesPerRow, 
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    
    // Draw the pixel we are interested in onto the bitmap context
    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    CGContextRelease(context);
    
    // Convert color values [0..255] to floats [0.0..1.0]
    //CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
    //CGFloat green = (CGFloat)pixelData[1] / 255.0f;
    //CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
    //CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
    //rgbArray[offset + y * scanSize + x] = a << 24 | r << 16 | g << 8 | b;
    //return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    
    int red = pixelData[0];
    int green = pixelData[1];
    int blue = pixelData[2];
    int alpha = pixelData[3];
    int rgbValue = alpha << 24 | red << 16 | green << 8 | blue;
    //NSLog(@"r = %d  g= %d  b = %d  a = %d  value=%d ", red, green, blue, alpha, rgbValue);
    return rgbValue;
}

@end
